import os
import logging
import time
from video_frame_extractor import VideoFrameExtractor
from audio_transcriber import AudioExtractorTranscriber
from frame_analyzer import SimpleImageAnalyzer
from speech_analyzer import SpeechAnalyzer
from content_analyzer import ContentAnalyzer
from score_generator import Scorer
from bias_detector import BiasDetector

class Pipeline:
    def __init__(self, modules=None):
        """
        用指定的模块初始化流水线。
        
        参数:
            modules (dict, optional): 将模块名称映射到模块实例的字典。如果为None，则创建默认模块。
        """
        # 配置日志
        logging.basicConfig(
            level=logging.INFO,
            format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
        )
        self.logger = logging.getLogger(__name__)
        
        # 如果没有提供模块，创建默认模块
        if modules is None:
            self.logger.info("使用默认模块初始化流水线")
            modules = {
                'frame_extractor': VideoFrameExtractor(),
                'audio_extractor': AudioExtractorTranscriber(),
                'visual_analyzer': SimpleImageAnalyzer(),
                'audio_analyzer': SpeechAnalyzer(),
                'content_analyzer': ContentAnalyzer(),
                'scorer': Scorer(),
                'bias_detector': BiasDetector()
            }
        
        self.modules = modules
        self.logger.info(f"流水线初始化完成，包含以下模块: {', '.join(self.modules.keys())}")
    
    def process_video(self, video_path, job_keywords=None, candidate_name=None, demographics=None):
        """
        通过整个流水线处理单个候选人视频。
        
        参数:
            video_path (str): 候选人视频文件的路径
            job_keywords (list, optional): 工作相关关键词列表
            candidate_name (str, optional): 候选人姓名
            demographics (dict, optional): 候选人人口统计学信息，用于偏见分析
            
        返回:
            dict: 完整的处理结果
        """
        start_time = time.time()
        self.logger.info(f"开始处理视频: {video_path}")
        
        # 生成唯一ID，避免中文路径问题
        video_id = f"candidate_{int(time.time())}"
        video_basename = os.path.basename(video_path)
        
        # 初始化数据对象
        data = {
            'video_path': video_path,
            'video_id': video_id,
            'job_keywords': job_keywords or [],
            'candidate_name': candidate_name or os.path.splitext(video_basename)[0],
            'demographics': demographics or {}
        }
        
        try:
            # 1. 提取视频帧
            if 'frame_extractor' in self.modules:
                self.logger.info("步骤1: 提取视频帧")
                frame_result = self.modules['frame_extractor'].process({
                    'video_path': video_path,
                    'sample_rate': 5  # 每5帧提取一帧
                })
                data['frames'] = frame_result.get('frames', [])
                data['video_metadata'] = frame_result.get('metadata', {})
            
            # 2. 提取和转录音频
            if 'audio_extractor' in self.modules:
                self.logger.info("步骤2: 提取和转录音频")
                audio_result = self.modules['audio_extractor'].process({
                    'video_path': video_path 
                })
                data['transcript'] = audio_result.get('transcript', "")
                data['audio_path'] = audio_result.get('audio_path', "")
                data['transcript_chunks'] = audio_result.get('chunks', [])
                
                # 保存转录结果到transcripts文件夹
                transcripts_dir = "transcripts"
                os.makedirs(transcripts_dir, exist_ok=True)
                
                # 使用候选人姓名和视频ID组合生成文件名
                candidate_name = data['candidate_name']
                transcript_filename = f"{candidate_name}_{video_id}.json"
                transcript_path = os.path.join(transcripts_dir, transcript_filename)
                
                # 保存为JSON文件
                import json
                transcript_data = {
                    'transcript': data['transcript'],
                    'chunks': data['transcript_chunks']
                }
                
                try:
                    with open(transcript_path, 'w', encoding='utf-8') as f:
                        json.dump(transcript_data, f, ensure_ascii=False, indent=2)
                    self.logger.info(f"转录结果已保存到: {transcript_path}")
                except Exception as e:
                    self.logger.error(f"保存转录结果失败: {str(e)}")
            
            # 3. 分析视觉特征
            if 'visual_analyzer' in self.modules and 'frames' in data:
                self.logger.info("步骤3: 分析视觉特征")
                # 保存帧到临时文件夹
                frames_folder = f"frames/{video_id}"
                os.makedirs(frames_folder, exist_ok=True)
                
                for i, frame in enumerate(data['frames']):
                    frame_path = os.path.join(frames_folder, f"frame_{i:04d}.jpg")
                    if not os.path.exists(os.path.dirname(frame_path)):
                        os.makedirs(os.path.dirname(frame_path), exist_ok=True)
                    import cv2
                    cv2.imwrite(frame_path, frame)
                
                visual_features = self.modules['visual_analyzer'].analyze_image_folder(frames_folder)
                data['visual_features'] = visual_features
                data['frames_folder'] = frames_folder
            
            # 4. 分析音频特征
            if 'audio_analyzer' in self.modules:
                self.logger.info("步骤4: 分析音频特征")
                audio_features = self.modules['audio_analyzer'].analyze_speech(data['video_path'])
                data['audio_features'] = audio_features
            
            # 5. 分析内容特征
            if 'content_analyzer' in self.modules and 'transcript' in data:
                self.logger.info("步骤5: 分析内容特征")
                content_features = self.modules['content_analyzer'].analyze_transcript(
                    data['transcript'], 
                    data['job_keywords']
                )
                data['content_features'] = content_features
            
            # 6. 生成评分
            if 'scorer' in self.modules:
                self.logger.info("步骤6: 生成评分")
                # 保存各类型特征到指定文件夹，以便评分模块读取
                self._save_features_for_scoring(data)
                
                # 调用评分器
                scores = self.modules['scorer'].process(data['video_id'])
                data['scores'] = scores
            
            # 7. 偏见检测（如果有人口统计学信息）
            if 'bias_detector' in self.modules and data.get('demographics') and data.get('scores'):
                self.logger.info("步骤7: 偏见检测分析")
                bias_results = self.modules['bias_detector'].check_bias(
                    [data['scores']], 
                    {data['video_id']: data['demographics']}
                )
                data['bias_analysis'] = bias_results
                
                # 保存偏见分析报告
                bias_output_dir = f"bias_analysis_results/{data['video_id']}"
                report_paths = self.modules['bias_detector'].save_bias_report(
                    bias_results, 
                    bias_output_dir
                )
                data['bias_report_paths'] = report_paths
            
            process_time = time.time() - start_time
            self.logger.info(f"视频处理完成，耗时: {process_time:.2f}秒")
            data['process_time'] = process_time
            
            return data
            
        except Exception as e:
            self.logger.error(f"处理视频时出错: {str(e)}")
            return {
                'error': str(e),
                'video_id': video_id,
                'video_path': video_path
            }
    
    def _save_features_for_scoring(self, data):
        """
        将特征保存到特定格式的文件中，以便评分模块读取
        
        参数:
            data (dict): 包含各种特征的数据对象
        """
        import csv
        import os
        
        video_id = data['video_id']
        
        # 1. 保存内容分析结果
        if 'content_features' in data:
            content_dir = f"analysis_results/{video_id}"
            os.makedirs(content_dir, exist_ok=True)
            
            with open(f"{content_dir}/analysis.csv", 'w', newline='') as f:
                writer = csv.writer(f)
                writer.writerow(['Metric', 'Value'])
                
                content_features = data['content_features']
                if isinstance(content_features, dict):
                    for key, value in content_features.items():
                        if key == 'keyword_matches':
                            continue  # 跳过复杂对象
                        writer.writerow([key.replace('_', ' ').title(), value])
        
        # 2. 保存语音分析结果
        if 'audio_features' in data:
            speech_dir = f"speech_analysis_results/{video_id}"
            os.makedirs(speech_dir, exist_ok=True)
            
            with open(f"{speech_dir}/speech_analysis.csv", 'w', newline='') as f:
                writer = csv.writer(f)
                audio_features = data['audio_features']
                
                # 确定CSV头部
                if 'frames' in audio_features:
                    headers = list(audio_features['frames'][0].keys()) if audio_features['frames'] else []
                    writer.writerow(headers)
                    
                    # 写入每一帧的数据
                    for frame in audio_features['frames']:
                        writer.writerow(frame.values())
        
        # 3. 保存视觉分析结果
        if 'visual_features' in data:
            visual_dir = f"visual_analysis_results/{video_id}"
            os.makedirs(visual_dir, exist_ok=True)
            
            with open(f"{visual_dir}/frame_analysis.csv", 'w', newline='') as f:
                writer = csv.writer(f)
                visual_features = data['visual_features']
                
                if 'frames' in visual_features:
                    headers = list(visual_features['frames'][0].keys()) if visual_features['frames'] else []
                    writer.writerow(headers)
                    
                    for frame in visual_features['frames']:
                        writer.writerow(frame.values())

# 使用示例
if __name__ == "__main__":
    # 创建流水线实例
    pipeline = Pipeline()
    
    # 指定视频路径和工作关键词
    video_path = "videos/example.mp4"
    job_keywords = ["communication", "teamwork", "problem solving"]
    
    # 添加示例人口统计信息用于偏见分析
    demographics = {
        "gender": "female",
        "age_group": "30-40"
    }
    
    # 处理视频
    try:
        result = pipeline.process_video(
            video_path=video_path,
            job_keywords=job_keywords,
            candidate_name="Example Candidate",
            demographics=demographics
        )
        
        # 打印处理结果摘要
        print("\n==== 处理结果摘要 ====")
        if 'error' in result:
            print(f"处理失败: {result['error']}")
        else:
            print(f"候选人: {result['candidate_name']}")
            print(f"视频ID: {result['video_id']}")
            
            if 'scores' in result:
                scores = result['scores']
                print(f"\n总分: {scores['overall_score']}/100")
                print("\n组件得分:")
                for category, score in scores['component_scores'].items():
                    print(f"- {category}: {score:.1f}")
            
            if 'bias_analysis' in result:
                print("\n偏见分析结果:")
                for attribute, analysis in result['bias_analysis'].items():
                    if 'error' in analysis:
                        print(f"- {attribute}: 分析错误 - {analysis['error']}")
                    else:
                        bias_level = analysis.get('bias_level', '未知')
                        impact = analysis.get('disparate_impact', 0)
                        print(f"- {attribute}: 偏见程度 {bias_level} (差异影响比率: {impact:.2f})")
            
            print(f"\n处理耗时: {result.get('process_time', 0):.2f}秒")
    except Exception as e:
        print(f"运行流水线时出错: {str(e)}")
